#include <linux/vmalloc.h>
#include <asm/pgtable_types.h>

#include <linux/module.h>

#include "../include/testing_commands.h"

#include "print_test.h"

struct tester_data TESTER;

extern char _binary_mod_bin_start;
extern char _binary_mod_bin_end;
extern int _binary_mod_bin_size;

void set_comm(void)
{
  //PML4E -> PDPTE
  map   (0, 0, 1);
  flags (0, 0, PF_PRESENT | PF_WRITE);
  
  //PDPTE -> PDE
  map   (1, 0, 2);
  flags (1, 0, PF_PRESENT | PF_WRITE);
  
  //PDE -> PTE
  map   (2, 0, 3);
  flags (2, 0, PF_PRESENT | PF_WRITE);
  
  //PTE -> 4kb page (.text), 0x10000
  map   (3, 16, 4);
  flags (3, 16, PF_PRESENT | PF_WRITE);
  
  //PTE -> 4kb page (.data), 0x20000
  map   (3, 32, 5);
  flags (3, 32, PF_PRESENT | PF_WRITE);
  
  addr  ("write 0.0.0.16", CMD_WRITE, vaddr64_5(0,0,0,16,0), 4);
  addr  ("run 0.0.0.16", CMD_RUN, vaddr64_5(0,0,0,16,0), 4);
  addr  ("read 0.0.0.16", CMD_READ, vaddr64_5(0,0,0,16,0), 4);
  
  addr  ("write 0.0.0.32", CMD_WRITE, vaddr64_5(0,0,0,32,0), 5);
  addr  ("run 0.0.0.32", CMD_RUN, vaddr64_5(0,0,0,32,0), 5);
  addr  ("read 0.0.0.32", CMD_READ, vaddr64_5(0,0,0,32,0), 5);
  
  addr  ("flush", CMD_FLUSH, 0, 0);
  addr  ("end", CMD_END, 0, 0);
}




static int my_init(void)
{
  int res;
  int glob;
  
  info("\n=======begin=======\n");
  if (init_tester() != 0)
    return 1;
  set_comm();
  
  info("initialization completed\n");
  
  res = run_test();
  print_test_results(res);
  
  memcpy (TESTER.pages[4].virt, &_binary_mod_bin_start, (unsigned long)&_binary_mod_bin_size);
  
  test_context();
  PREPARE_INTERRUPTS_HERE("my_intret");
  
  res = ( (int (*)(int, int))0x10000 )(10, 7);
  glob = *(int *)0x20000;
  
  asm volatile("my_intret:");
  linux_context();
  info ("exceptions: \n");
  print_int_info((struct interrupt_info *)&int_info);
  info ("res: %d\nglob: %d\n", res, glob);
  
  free_memory();
  
  info("\nfinish\n");
  
  return 0;
}

static void my_exit(void) {
  info("exit\n");
}

module_init(my_init);
module_exit(my_exit);
